/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2021-03-12 11:26:07
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-04-01 15:41:18
 * @Description: file content
 */

import { Service } from "egg";

/** 批量设置角色权限功能，api接收到的数据类型 */
export interface batchRolePermission {
  roleIdList: Array<string | number>;
  menusList: Array<string | number>;
  commonList: {
    [key: string]: Array<string | number>;
  };
  customList: {
    [key: string]: Array<string | number>;
  };
}

export default class Permission extends Service {
  /** 删除[]多个角色的权限列表。 */
  async emptyRoleListPermisson(
    roleList: batchRolePermission["roleIdList"] = []
  ) {
    // const t = await this.ctx.model.transaction();
    if (typeof roleList === "string") {
      roleList = [roleList];
    }
    if (!Array.isArray(roleList) || roleList.length < 1) {
      return;
    }
    const model = this.ctx.model.Sys.RolePermission;
    return await model.destroy({
      where: {
        role_id: roleList,
      },
      // transaction: t,
    });
  }

  /** 处理前端的数据，拼接成为可插入数据库的list */
  handleDataTodbData(data: batchRolePermission): any[] {
    const insertDataList: Array<any> = [];
    // console.log("555", data);
    const uid = this.ctx.loginUserInfo.uid;

    data.roleIdList.forEach((role) => {
      // 菜单权限
      data.menusList.forEach((menu) => {
        insertDataList.push({
          role_id: role,
          menu_id: menu,
          perm_id: menu,
          type: 0,
          create_user_id: uid,
          edit_user_id: uid,
        });
      });
      // 通用权限
      Object.keys(data.commonList).forEach((menu_id) => {
        data.commonList[menu_id].forEach((item) => {
          insertDataList.push({
            role_id: role,
            menu_id: menu_id,
            perm_id: item,
            type: 1,
            create_user_id: uid,
            edit_user_id: uid,
          });
        });
      });
      // 自定义权限 与通用一样的。
      Object.keys(data.customList).forEach((menu_id) => {
        data.customList[menu_id].forEach((item) => {
          insertDataList.push({
            role_id: role,
            menu_id: menu_id,
            perm_id: item,
            type: 2,
            create_user_id: uid,
            edit_user_id: uid,
          });
        });
      });
    });
    return insertDataList;
  }

  /** 批量设置多个角色的权限功能。 */
  async batchPostRolesPermission(data: batchRolePermission) {
    const insertlist = this.ctx.service.sys.permission.handleDataTodbData(data);
    const delState = await this.ctx.service.sys.permission.emptyRoleListPermisson(
      data.roleIdList
    );

    if ((delState as number) >= 0 && insertlist.length > 0) {
      const res = await this.app.model.Sys.RolePermission.bulkCreate(
        insertlist
      );
      // console.log(res);
      return { insertRows: res.length };
    } else {
      return { insertRows: 0 };
    }
  }

  /** 根据角色id获取其所有的权限，并做成对象格式。
   * 用着角色修改权限时，拼接成 batchRolePermission interface的权限。*/
  async getAllPermByRoleId(role_id: number) {
    const ret = await this.app.model.Sys.RolePermission.findAll({
      raw: true,
      where: {
        role_id,
      },
    });
    const sendData: batchRolePermission = {
      roleIdList: [role_id],
      menusList: [],
      commonList: {},
      customList: {},
    };
    ret.forEach((item) => {
      if (item.type === 0) {
        sendData.menusList.push(item.perm_id);
      } else if (item.type === 1) {
        if (!sendData.commonList[item.menu_id]) {
          sendData.commonList[item.menu_id] = [];
        }
        sendData.commonList[item.menu_id].push(item.perm_id);
      } else if (item.type === 2) {
        if (!sendData.customList[item.menu_id]) {
          sendData.customList[item.menu_id] = [];
        }
        sendData.customList[item.menu_id].push(item.perm_id);
      }
    });
    // console.log(sendData);
    return sendData;
  }

  /**
   * 根据 一个用户 角色list获取其所有权限的标识。用在前端赋值控制权限上。
   */
  async getAllPermByUser(user_id: number) {
    const userInfo = await this.ctx.model.Sys.User.findOne({
      raw: true,
      where: {
        id: user_id,
      },
    });

    const ret = {
      custom_perm: [] as any[],
      menus_perm: [],
      common_perm: {},
    };

    if (!userInfo) {
      return ret;
    }

    // console.log(userInfo);
    // console.log(userInfo?.role_ids);

    const role_ids = userInfo.role_ids ? userInfo.role_ids.split(",") : [];

    // 如果没有角色
    if (role_ids.length < 1) {
      return ret;
    }
    // 获取这些角色的类型2，自定义权限的的所有列表并去重获得权限标识表。
    const all_role_custom_perms_list = await this.ctx.model.Sys.RolePermission.findAll(
      {
        raw: true,
        where: {
          role_id: role_ids,
          type: 2,
        },
        attributes: {
          include: [
            [
              this.app.model.Sequelize.col("role_perm_perm.cname"),
              "perm_cname",
            ],
            [
              this.app.model.Sequelize.col("role_perm_perm.ename"),
              "perm_ename",
            ],
          ],
          exclude: ["createdAt", "updatedAt", "create_user_id", "edit_user_id"],
        } as any,
        include: {
          model: this.ctx.model.Sys.PermissionList,
          as: "role_perm_perm",
          attributes: [],
        },
      }
    );
    // 授权标识列表
    let ename_list = all_role_custom_perms_list.map(
      (item) => (item as any).perm_ename
    );
    // console.log(ename_list);

    ename_list = Array.from(new Set(ename_list));
    ret.custom_perm = ename_list;

    // 获取角色的通用功能权限表
    const all_role_common_perm_list = await this.ctx.model.Sys.RolePermission.findAll(
      {
        raw: true,
        attributes: ["perm_id", "menu_id"], //通用功能的perm_id是前端定义固定的。
        where: {
          type: 1,
          role_id: role_ids,
        },
      }
    );
    // 把通用菜单权限做成menu_id:[1,2]的形式。
    all_role_common_perm_list.forEach((item) => {
      // console.log(item.menu_id);
      if (!ret.common_perm[item.menu_id]) {
        ret.common_perm[item.menu_id] = [];
      }
      ret.common_perm[item.menu_id].push(item.perm_id);
    });
    // console.log(all_role_common_perm_list);
    // console.log(ename_list);
    return ret;
  }
}
